package com.chenjt.netty.nine_charEncodeAndDecode;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;

/**
 * 注释：
 *
 * @author chenjt
 * @date 2024/8/24 9:05
 */
public class Test1 {


    public static void main(String[] args) throws Exception {
        // 文件编码格式为UTF-8
        String inputFile = "src/main/java/com/chenjt/netty/nine_charEncodeAndDecode/Test1_in.txt";
        String outputFile = "src/main/java/com/chenjt/netty/nine_charEncodeAndDecode/Test1_out.txt";

        RandomAccessFile inputRandomAccessFile = new RandomAccessFile(inputFile, "r");
        RandomAccessFile outputRandomAccessFile = new RandomAccessFile(outputFile, "rw");

        long inputLength = new File(inputFile).length();

        FileChannel inputFileChannel = inputRandomAccessFile.getChannel();
        FileChannel outputFileChannel = outputRandomAccessFile.getChannel();

        // 数据映射到内存中，权限是只读，通过操作 MappedByteBuffer 达到操作文件的内容
        MappedByteBuffer inputData = inputFileChannel.map(FileChannel.MapMode.READ_ONLY, 0, inputLength);

        System.out.println("===========");
        // 列出系统上所有的字符集
        Charset.availableCharsets().forEach((k,v)->{
            System.out.println(k + "," + v);
        });
        System.out.println("===========");


//        Charset charset = Charset.forName("utf-8");
        Charset charset = Charset.forName("iso-8859-1");
        CharsetDecoder decoder = charset.newDecoder();
        CharsetEncoder encoder = charset.newEncoder();

        /**
         * 这里用iso-8859-1（8bit表示一个字符）对UTF-8的文件进行解码，
         * 解码时英文不会有问题，因为英文状态下都是8bit表示一个字符，
         * 但是中文就不行了，中文在UTF-8下是三个字节表示一个中文，
         * 用iso-8859-1解码时是一个字节一个字节解码的，解码过程中(debug查看)去获取对应的字符，
         * 就会发现获取中文字符时是乱码的，UTF-8是3个字节表示一个中文，这里就会看到用ISO-8859-1
         * 一个字节来表示一个中文，拿中文的第一个字节去ISO-8859-1编码表中查看，就会发现该乱码内容和
         * 该字节在ISO-8859-1表中的编码内容一致
         *
         * ByteBuffer outputData = encoder.encode(charBuffer);
         * 但是最后还是按iso-8859-1去编码写入文件，该文件是UTF-8存储形式的，解码不会有问题
         * 因为UTF-8解码中文是按3个字节去解码的，解码英文还是按照8bit去解码，所以不会乱码
         *
         * 注意：文件都是按字节的形式去存储数据的，而编解码方式，是按照人能看得懂的方式
         * 去把字节按照特定的编解码规则转换成对应的文字内容
         *
         * 所以在读取UTF-8文件的内容时，
         * 都是一个字节一个字节读取出来的，如果采用了ISO-8859-1解码方式去读取，只要在这个
         * 解码的过程中把解码之后的字节内容打印出来，就会发现是乱码的
         * 但是，用了ISO-8859-1去解码，再用ISO-8859-1的方式去编码存入文件，中间没有改变内容，
         * 文件用UTF-8的存储方式去存储文件，最终的显示是不会乱码的，因为存储都是一个字节一个字节进去的，
         * 最终显示是3个字节为一个中文，所以不会出现乱码情况
         * 如果文件是用ISO-8859-1去存储的，就会发现中文是乱码的，3个字节为一个中文，现在1个字节就把它解码出来了，自然无法显示正确的内容
         *
         * 如果读取文件内容采用ISO-8859-1解码，用UTF-8去编码写入文件，解码之后的内容已经是错误的了，这时候再用错误的内容去编码，
         * 会发现写入文件时（存储方式为UTF-8）已经是乱码了
         *
         */
        // 将字节数组转换为字符串
        CharBuffer charBuffer = decoder.decode(inputData);

        // 一个换行占两个字符？这里要到索引14打印的才是中文
//        System.out.println(charBuffer.get(14));

        // 将字符串转换为字节数组
        ByteBuffer outputData = encoder.encode(charBuffer);
        // 这里用UTF-8去编码文件会造成中文乱码，一开始用iso-8859-1去解码已经是错误的了，用错误的内容再用utf-8去编码就更错了
//        ByteBuffer outputData = Charset.forName("utf-8").encode(charBuffer);


        outputFileChannel.write(outputData);

        inputRandomAccessFile.close();
        outputRandomAccessFile.close();


    }

}
